<template>
  <div class="table-container">
    <div
      v-if="innerTableOption.option.showHeaderBtn"
      class="flex-between"
    >
      <div class="flex-between">
        <el-button
          v-for="(item,index) in permissionBtn(innerButtonData,this)"
          :key="index"
          type="primary"
          @click="emitEvent($event,item.action)"
        >{{ item.label }}
        </el-button>
      </div>
    </div>
    <el-table
      v-if="showTable"
      ref="multipleTable"
      :data="tableData"
      :height="innerTableOption.option.height"
      :max-height="innerTableOption.option.maxHeight"
      :stripe="innerTableOption.option.stripe"
      :border="innerTableOption.option.border"
      :size="innerTableOption.option.size"
      :fit="innerTableOption.option.fit"
      :show-header="innerTableOption.option.showHeader"
      :highlight-current-row="innerTableOption.option.highlightCurrentRow"
      :current-row-key="innerTableOption.option.currentRowKey"
      :row-class-name="innerTableOption.option.rowClassName"
      :row-style="innerTableOption.option.rowStyle"
      :cell-class-name="innerTableOption.option.cellClassName"
      :cell-style="innerTableOption.option.cellStyle"
      :header-row-class-name="innerTableOption.option.headerRowClassName"
      :header-row-style="innerTableOption.option.headerRowStyle"
      :header-cell-class-name="innerTableOption.option.headerCellClassName"
      :header-cell-style="innerTableOption.option.headerCellStyle"
      :row-key="innerTableOption.option.rowKey"
      :empty-text="innerTableOption.option.emptyText"
      :default-expand-all="innerTableOption.option.defaultExpandAll"
      :expand-row-keys="innerTableOption.option.expandRowKeys"
      :default-sort="innerTableOption.option.defaultSort"
      :tooltip-effect="innerTableOption.option.tooltipEffect"
      :show-summary="innerTableOption.option.showSummary"
      :sum-text="innerTableOption.option.sumText"
      :summary-method="innerTableOption.option.summaryMethod"
      :span-method="innerTableOption.option.spanMethod"
      :select-on-indeterminate="innerTableOption.option.selectOnIndeterminate"
      :indent="innerTableOption.option.indent"
      :lazy="innerTableOption.option.lazy"
      :load="innerTableOption.option.load"
      :tree-props="innerTableOption.option.treeProps"
      class="table"
      @select="(selection, row)=>{if(typeof innerTableOption.event.select == 'function') innerTableOption.event.select(selection, row)}"
      @select-all="(selection)=>{if(typeof innerTableOption.event.selectAll == 'function') innerTableOption.event.selectAll(selection)}"
      @selection-change="(selection)=>{if(typeof innerTableOption.event.selectionChange == 'function') innerTableOption.event.selectionChange(selection)}"
      @cell-mouse-enter="(row, columnItem, cell, event)=>{if(typeof innerTableOption.event.cellMouseEnter == 'function') innerTableOption.event.cellMouseEnter(row, columnItem, cell, event)}"
      @cell-mouse-leave="(row, columnItem, cell, event)=>{if(typeof innerTableOption.event.cellMouseLeave == 'function') innerTableOption.event.cellMouseLeave(row, columnItem, cell, event)}"
      @cell-click="(row, columnItem, cell, event)=>{if(typeof innerTableOption.event.cellClick == 'function') innerTableOption.event.cellClick(row, columnItem, cell, event)}"
      @cell-dblclick="(row, columnItem, cell, event)=>{if(typeof innerTableOption.event.cellDblclick == 'function') innerTableOption.event.cellDblclick(row, columnItem, cell, event)}"
      @row-click="(row, columnItem, event)=>{if(typeof innerTableOption.event.rowClick == 'function') innerTableOption.event.rowClick(row, columnItem, event)}"
      @row-contextmenu="(row, columnItem, event)=>{if(typeof innerTableOption.event.rowContextmenu == 'function') innerTableOption.event.rowContextmenu(row, columnItem, event)}"
      @row-dblclick="(row, columnItem, event)=>{if(typeof innerTableOption.event.rowDblclick == 'function') innerTableOption.event.rowDblclick(row, columnItem, event)}"
      @header-click="(columnItem, event)=>{if(typeof innerTableOption.event.headerClick == 'function') innerTableOption.event.headerClick(columnItem, event)}"
      @header-contextmenu="(columnItem, event)=>{if(typeof innerTableOption.event.headerContextmenu == 'function') innerTableOption.event.headerContextmenu(columnItem, event)}"
      @sort-change="sortChange"
      @filter-change="(filters)=>{if(typeof innerTableOption.event.filterChange == 'function') innerTableOption.event.filterChange(filters)}"
      @current-change="(currentRow, oldCurrentRow)=>{if(typeof innerTableOption.event.currentChange == 'function') innerTableOption.event.currentChange(currentRow, oldCurrentRow)}"
      @header-dragend="(newWidth, oldWidth, columnItem, event)=>{if(typeof innerTableOption.event.headerDragend == 'function') innerTableOption.event.headerDragend(newWidth, oldWidth, columnItem, event)}"
      @expand-change="(row, expland)=>{if(typeof innerTableOption.event.expandChange == 'function') innerTableOption.event.expandChange(row, expland)}"
    >
      <el-table-column
        v-if="innerTableOption.option.enableSelected"
        type="selection"
        :width="innerTableOption.option.selectedWidth"
        align="center"
      />
      <template v-for="(item,index) in innerColumn.data">
        <el-table-column
          v-if="item.show"
          :key="item.key?item.key:index"
          :type="item.type"
          :index="item.index"
          :column-key="item.columnKey"
          :label="item.label"
          :prop="item.prop"
          :width="item.width"
          :min-width="item.minWidth"
          :fixed="item.fixed"
          :render-header="item.renderHeader"
          :sortable="(item.prop!='index'&& item.sortable )?true:false"
          :sort-method="item.sortMethod"
          :sort-by="item.sortBy"
          :sort-orders="item.sortOrders"
          :resizable="item.resizable"
          :formatter="item.formatter"
          :show-overflow-tooltip="item.showOverflowTooltip"
          :align="item.align"
          :header-align="item.headerAlign"
          :class-name="item.className"
          :label-class-name="item.labelClassName"
          :selectable="item.selectable"
          :reserve-selection="item.reserveSelection"
          :filters="item.filters"
          :filter-placement="item.filterPlacement"
          :filter-multiple="item.filterMultiple"
          :filter-method="item.filterMethod"
          :filtered-value="item.filteredValue"
        >
          <template slot="header">
            <slot
              v-if="item.headSlotName"
              :name="item.headSlotName"
              :$index="index"
            />
          </template>
          <template slot-scope="scope">
            <table-rules
              v-if="item.slotName"
              :value="scope.row"
              :rules="item.rules"
              :size="item.size"
              :required="item.required"
            >
              <slot
                :name="item.slotName"
                :$index="scope.$index"
                :row="scope.row"
              />
            </table-rules>
            <div
              v-else-if="item.format"
              v-html="item.format(scope.row,scope.$index)"
            />
            <span v-else-if="item.prop=='index'">{{ scope.$index+1 }}</span>
            <span v-else>{{ scope.row[item.prop] }}</span>
          </template>
        </el-table-column>

      </template>

      <!-- 操作 -->
      <el-table-column
        v-if="innerColumn.operation"
        :label="innerColumn.operation.label"
        :fixed="innerColumn.operation.fixed"
        :width="innerColumn.operation.width"
        class="action"
      >
        <template slot-scope="scope">
          <span
            v-for="item in permissionBtn((typeof innerColumn.operation.data =='function'?innerColumn.operation.data(scope.row):innerColumn.operation.data),this)"
            :key="item.id"
            :class="item.class?item.class:'table-action'"
            @click.stop="emitEvent($event, item.action, scope.row)"
          >{{ item.label }}</span>
        </template>
      </el-table-column>
    </el-table>
    <div
      v-if="innerTableOption.option.showPagination"
      class="flex-between page"
    >
      <el-pagination
        :small="innerPagination.small"
        :background="innerPagination.background"
        :page-size="innerPagination.pageSize"
        :total="innerPagination.total"
        :page-sizes="innerPagination.pageSizes"
        :popper-class="innerPagination.popperClass"
        :disabled="innerPagination.disabled"
        :hide-on-single-page="innerPagination.hideOnSinglePage"
        layout="total, sizes"
        @size-change="sizeChange"
      />
      <el-pagination
        :current-page="innerPagination.pageNum"
        :background="innerPagination.background"
        :pager-count="innerPagination.pagerCount"
        :page-size="innerPagination.pageSize"
        :prev-text="innerPagination.prevText"
        :next-text="innerPagination.nextText"
        :disabled="innerPagination.disabled"
        layout=" prev, pager, next"
        :total="innerPagination.total"
        :hide-on-single-page="innerPagination.hideOnSinglePage"
        @current-change="currentChange"
        @prev-click="prevClick"
        @next-click="nextClick"
      />
    </div>
    <slot name="attention" />
  </div>
</template>

<script>
import tableRules from './tableRules'
export default {
  name: 'DataTable',
  components: {
    tableRules
  },
  props: {
    // buttonData [{action : 按钮点击方式,label : 显示的按钮值}]
    buttonData: {
      type: Array,
      default: () => {
        return []
      }
    },
    tableOption: {
      type: Object,
      default: null
    },
    column: {
      type: Object,
      default: () => {
        return {
          data: [], // 列
          operation: [] // 操作
        }
      }
    },
    // 数据
    tableData: {
      type: Array,
      default: () => {
        return []
      }
    },
    // 分页
    pagination: {
      type: Object,
      default: null
    }
  },
  data() {
    return {
      // buttonData [{action : 按钮点击方式,label : 显示的按钮值}]
      innerButtonData: {
        type: Array,
        default: () => {
          return []
        }
      },
      innerTableOption: {
        type: Object,
        default: () => {
          return { option: null, event: null }
        }
      },
      innerColumn: {
        type: Object,
        default: () => {
          return {
            data: [], // 列
            operation: [] // 操作
          }
        }
      },
      // 分页
      innerPagination: {
        pageNum: 1,
        pageSize: 10,
        total: 0
      },
      initTableOption: {
        option: {
          height: null,
          maxHeight: null,
          stripe: false,
          border: false,
          size: null,
          fit: true,
          showHeader: true,
          highlightCurrentRow: false,
          currentRowKey: null,
          rowClassName: null,
          rowStyle: null,
          cellClassName: null,
          cellStyle: null,
          headerRowClassName: null,
          headerRowStyle: null,
          headerCellClassName: 'header',
          headerCellStyle: null,
          rowKey: 'id',
          emptyText: this.$t('common.emptyText'),
          defaultExpandAll: false,
          expandRowKeys: null,
          defaultSort: { order: 'ascending' },
          tooltipEffect: 'dark',
          showSummary: false,
          sumText: this.$t('common.sumText'),
          summaryMethod: null,
          spanMethod: null,
          selectOnIndeterminate: true,
          indent: 16,
          lazy: null,
          load: null,
          treeProps: { hasChildren: 'hasChildren', children: 'children' },
          showPagination: true,
          enableSelected: false,
          selectedWidth: 55,
          showHeaderBtn: true
        },
        event: {
          select: null,
          selectAll: null,
          selectionChange: null,
          cellMouseEnter: null,
          cellMouseLeave: null,
          cellClick: null,
          cellDblclick: null,
          rowClick: null,
          rowContextmenu: null,
          rowDblclick: null,
          headerClick: null,
          headerContextmenu: null,
          sortChange: null,
          filterChange: null,
          headerDragend: null,
          expandChange: null,
          currentChange: null,
          sizeChange: null,
          prevClick: null,
          nextClick: null
        }
      },
      initPaginationOption: {
        small: false,
        background: false,
        pageSize: 10,
        total: null,
        pageCount: null,
        pagerCount: 7,
        pageNum: 1,
        pageSizes: [5, 10, 20, 50],
        popperClass: null,
        prevText: null,
        nextText: null,
        disabled: false,
        hideOnSinglePage: null
      },
      initColumnOption: {
        type: null,
        show: true,
        headSlotName: null,
        index: null,
        columnKey: null,
        rules: [],
        label: null,
        prop: null,
        width: null,
        minWidth: null,
        fixed: false,
        renderHeader: null,
        sortable: true,
        sortMethod: null,
        sortBy: null,
        sortOrders: null,
        size: 'medium',
        resizable: true,
        required: undefined,
        formatter: null,
        showOverflowTooltip: false,
        align: 'left',
        headerAlign: null,
        className: null,
        labelClassName: null,
        selectable: null,
        reserveSelection: false,
        filters: null,
        filterPlacement: null,
        filterMultiple: true,
        filteredValue: null
      },
      selectColumn: [],
      showTable: false
    }
  },
  computed: {
    permissionBtn() {
      // eslint-disable-next-line no-unused-vars
      var that = this
      // eslint-disable-next-line eqeqeq
      return (rows) => {
        return rows.filter((item) => { return that.$checkBtnPermission(item.permission) })
      }
    }
  },
  watch: {
    // buttonData [{action : 按钮点击方式,label : 显示的按钮值}]
    buttonData: {
      handler(val) {
        this.innerButtonData = val
      },
      deep: true
    },
    // buttonData [{action : 按钮点击方式,label : 显示的按钮值}]
    pagination: {
      handler(val) {
        this.innerPagination = Object.assign({}, this.initPaginationOption, val)
      },
      deep: true
    },
    tableOption: {
      handler(val) {
        this.innerTableOption = Object.assign({}, this.initTableOption, val)
        if (!this.pagination) {
          this.innerTableOption.option.showPagination = false
        }
      },
      deep: true
    },
    column: {
      handler(val) {
        const that = this
        this.innerColumn = { operation: val.operation, data: [] }
        val.data.forEach((value, index, array) => { that.innerColumn.data.push(Object.assign({}, that.initColumnOption, value)) })
      },
      deep: true
    }
  },
  created() {
    const that = this
    this.innerTableOption = Object.assign({}, this.initTableOption, this.tableOption)
    this.innerPagination = Object.assign({}, this.initPaginationOption, this.pagination)
    if (!this.pagination) {
      this.innerTableOption.option.showPagination = false
    }
    this.innerColumn = { operation: this.column.operation, data: [] }
    this.column.data.forEach((value, index, array) => { that.innerColumn.data.push(Object.assign({}, that.initColumnOption, value)) })
    this.innerButtonData = this.buttonData
  },
  mounted() {
    this.resetTable()
  },
  methods: {
    sortChange(params) {
      if (typeof this.innerTableOption.event.sortChange === 'function') {
        this.innerTableOption.event.sortChange(params)
      }
      if (params.order === 'ascending') { params.order = 'ASC' }
      if (params.order === 'descending') { params.order = 'DESC' }
      this.innerPagination.pageNum = 1
      this.innerPagination.orderName = params.prop
      this.innerPagination.orderType = params.order
      this.$emit('update:pagination', this.innerPagination)
      this.$emit('search-event', this.innerPagination)
    },
    sizeChange(data) {
      if (typeof this.innerTableOption.event.sizeChange === 'function') {
        this.innerTableOption.event.sizeChange(data)
      }
      this.innerPagination.pageSize = data
      this.$emit('update:pagination', this.innerPagination)
      this.$emit('search-event', this.innerPagination)
    },
    currentChange(data) {
      if (typeof this.innerTableOption.event.currentChange === 'function') {
        this.innerTableOption.event.currentChange(data)
      }
      this.innerPagination.pageNum = data
      this.$emit('update:pagination', this.innerPagination)
      this.$emit('search-event', this.innerPagination)
    },
    prevClick(data) {
      if (typeof this.innerTableOption.event.prevClick === 'function') {
        this.innerTableOption.event.prevClick(data)
      }
      this.innerPagination.pageNum = data
      this.$emit('update:pagination', this.innerPagination)
      this.$emit('search-event', this.innerPagination)
    },
    nextClick(data) {
      if (typeof this.innerTableOption.event.nextClick === 'function') {
        this.innerTableOption.event.nextClick(data)
      }
      this.innerPagination.pageNum = data
      this.$emit('update:pagination', this.innerPagination)
      this.$emit('search-event', this.innerPagination)
    },
    emitEvent($event, click, data) {
      if (typeof click === 'function') click(data, $event)
    },
    resetTable() {
      // 默认选择所有column(除操作列)
      const selectColumn = []
      this.column.data.map((data) => {
        selectColumn.push(data.label)
      })
      this.selectColumn = selectColumn
      this.$nextTick(() => {
        this.handleCheck()
      })
    },
    // 处理check
    handleCheck(e) {
      this.showTable = false
      this.column.data.map((data) => {
        data.show = false
        this.selectColumn.map((item) => {
          // eslint-disable-next-line eqeqeq
          if (item == data.label) {
            data.show = true
          }
        })
      })
      this.$nextTick(() => {
        this.showTable = true
      })
    },
    toggleRowSelection(rows, selected = true) {
      rows.map((row) => {
        this.$refs.multipleTable.toggleRowSelection(row, selected)
      })
    },
    clearSelection() {
      this.$refs.multipleTable.clearSelection()
    },
    toggleAllSelection() {
      this.$refs.multipleTable.toggleAllSelection()
    },
    toggleRowExpansion(row, expanded) {
      this.$refs.multipleTable.toggleRowExpansion(row, expanded)
    },
    setCurrentRow(row) {
      this.$refs.multipleTable.setCurrentRow(row)
    },
    clearSort() {
      this.$refs.multipleTable.clearSort()
    },
    clearFilter(columnKey) {
      this.$refs.multipleTable.clearFilter(columnKey)
    },
    doLayout() {
      this.$refs.multipleTable.doLayout()
    },
    sort(prop, order) {
      this.$refs.multipleTable.doLayout(prop, order)
    }
  }
}
</script>

<style lang="scss" scoped>
.table-action {
  border-left: 1px solid #efedf0;
  padding: 0 10px;
  font-size: 13px;
  cursor: pointer;
  color: #1890ff;
}

.cell span:first-of-type {
  border-left: none;
  padding-left: 0px;
}
</style>

<style scoped>
.el-table .cell > .drop {
  width: 5px;
  height: 5px;
  background-color: #67c23a;
  border-radius: 5px;
  vertical-align: middle;
}
</style>

